package ui;

import java.awt.AWTEvent;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D.Float;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

public class FullScreenFrame extends JFrame {

	private FramePane pnlFrame;
	private Float bounds = new Float(0f, 0f, 0f, 0f, 15f, 15f);
	private Float innerBounds = new Float(0f, 0f, 0f, 0f, 8f, 8f);
	private Float innerBounds2 = new Float(0f, 0f, 0f, 0f, 8f, 8f);
	private Path2D shape;
	private boolean unPaused;

	public FullScreenFrame (BufferedImage backgroundOrigin) {
		setTitle("Tetris");
		setUndecorated(true);
		pnlFrame = new FramePane(this, backgroundOrigin);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setBounds(0, 0, Constants.SCREEN_SIZE.width, Constants.SCREEN_SIZE.height);
		setContentPane(pnlFrame);
		setVisible(true);

		addWindowFocusListener(new WindowAdapter() {});
	}

	public void fadeIn () {
		new Thread() {
			@Override
			public void run () {
				for (float i = -0.1f, j = -0.1f, opacity = 0f; opacity < 1f; i += 0.014f, j += 0.014f, opacity += 0.1f) {
					synchronized (this) {
						Path2D p = new Path2D.Float(shape);
						AffineTransform trans = new AffineTransform();
						trans.translate(-bounds.width * i, -bounds.height * j);
						trans.shear(i, j);
						p.transform(trans);
						setOpacity(opacity);
						setShape(p);
						try {
							Thread.sleep(5);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				setOpacity(1);
				setShape(shape);
			}
		}.start();
	}

	public void fadeOut () {
		for (float i = 0f, j = 0f, opacity = 1f; opacity > 0f; i += 0.01f, j += 0.01f, opacity -= 0.1f) {
			Path2D p = new Path2D.Float(shape);
			AffineTransform trans = new AffineTransform();
			trans.translate(bounds.width * i, bounds.height * j);
			trans.shear(i, j);
			p.transform(trans);
			setOpacity(opacity);
			setShape(p);
			try {
				Thread.sleep(5);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void setState (int state) {
		if (state == Frame.ICONIFIED) {
			fadeOut();
		}
		super.setState(state);
	}

	@Override
	public void setVisible (boolean visible) {
		if (visible) {
			super.setVisible(true);
			fadeIn();
		} else {
			fadeOut();
			super.setVisible(false);
		}
	}

	public void setFakeFrameShape (float x, float y, float width, float height, float x2, float y2, float width2, float height2, float paddingX, float paddingY) {
		bounds.setRoundRect(x, y, width, height, bounds.arcwidth, bounds.archeight);
		innerBounds.setRoundRect(x2 - paddingX, y2 - paddingY, width2 + 2 * paddingX, height2 + 2 * paddingY, innerBounds.arcwidth, innerBounds.archeight);
		innerBounds2.setRoundRect(x2, y2, width2, height2, innerBounds.arcwidth, innerBounds.archeight);
		shape = new Path2D.Float();
		shape.setWindingRule(Path2D.WIND_EVEN_ODD);
		shape.append(bounds, true);
		shape.append(innerBounds, true);
		shape.append(innerBounds2, true);
		setShape(shape);
	}

	public Float getFakeBounds () {
		return bounds;
	}

	public Float getGamePanelBoundsOut () {
		return innerBounds;
	}

	public Float getGamePanelBoundsIn () {
		return innerBounds2;
	}

	@Override
	protected void processEvent (AWTEvent e) {
		switch (e.getID()) {
			case WindowEvent.WINDOW_LOST_FOCUS:
				if (pnlFrame.isStarted() && !pnlFrame.isPaused()) {
					unPaused = true;
					pnlFrame.setPaused(true);
				}
				fadeOut();
				super.processEvent(e);
				break;
			case WindowEvent.WINDOW_GAINED_FOCUS:
				fadeIn();
				super.processEvent(e);
				if (unPaused) {
					pnlFrame.setPaused(false);
					unPaused = false;
				}
				break;
			default:
				super.processEvent(e);
				break;
		}
	}

	@Override
	protected void processWindowEvent (WindowEvent e) {
		switch (e.getID()) {
			case WindowEvent.WINDOW_CLOSING:
				fadeOut();
				pnlFrame.closeRecorder();
				super.processWindowEvent(e);
				break;
			case WindowEvent.WINDOW_DEICONIFIED:
				super.processWindowEvent(e);
				fadeIn();
				break;
			default:
				super.processWindowEvent(e);
				break;
		}
	}

}
